package com.example.myapplication.ui.home.view

import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Color // Added for default shadow color
import android.os.Build
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.ViewConfiguration
import android.view.ViewGroup
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import android.view.animation.DecelerateInterpolator
import androidx.annotation.ColorInt // Added for color annotation
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.withStyledAttributes
import com.example.myapplication.R
import kotlin.math.abs

class AttractToEdgeView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {

    private var lastX = 0f
    private var lastY = 0f
    private var parentWidth = 0
    private var parentHeight = 0 // 新增：用于存储父布局的高度
    private var isDragging = false
    private val touchSlop: Int

    private var attractAnimator: ValueAnimator? = null

    private var attractToLeftEdgeEnabled: Boolean = true
    private var attractToRightEdgeEnabled: Boolean = true

    init {
        touchSlop = ViewConfiguration.get(context).scaledTouchSlop
//        outlineProvider = ViewOutlineProvider.BOUNDS // 强制使用边界作为轮廓
        // clipToOutline = true // 当设置了 elevation 后，这个通常默认为 true
        attrs?.let {
            context.withStyledAttributes(it, R.styleable.AttractToEdgeView) {
                attractToLeftEdgeEnabled = getBoolean(R.styleable.AttractToEdgeView_attractToLeftEdge, true)
                attractToRightEdgeEnabled = getBoolean(R.styleable.AttractToEdgeView_attractToRightEdge, true)

                // Shadow attributes
                val shadowElevation = getDimension(R.styleable.AttractToEdgeView_shadowElevation, 0f)
                if (shadowElevation > 0f) {
                    setShadowElevationValue(shadowElevation)
                }

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                    val defaultShadowColor = Color.BLACK // Default or a color from your theme
                    val ambientColor = getColor(R.styleable.AttractToEdgeView_shadowAmbientColor, defaultShadowColor)
                    val spotColor = getColor(R.styleable.AttractToEdgeView_shadowSpotColor, defaultShadowColor)
                    setShadowAmbientColorValue(ambientColor)
                    setShadowSpotColorValue(spotColor)
                }
            }
        }
    }

    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        // Allow dragging only if the view is visible and not animating
        if (visibility != View.VISIBLE || animation != null && !animation.hasEnded()) {
            return super.onInterceptTouchEvent(ev)
        }
        val action = ev.actionMasked
        if (action == MotionEvent.ACTION_DOWN) {
            lastX = ev.rawX
            lastY = ev.rawY
            // 获取父布局的尺寸，确保在拖动开始时获取最新的值
            if (parent is ViewGroup) {
                val p = parent as ViewGroup
                parentWidth = p.width
                parentHeight = p.height
            }
            isDragging = false
            attractAnimator?.cancel()
            parent.requestDisallowInterceptTouchEvent(true)
        }
        return super.onInterceptTouchEvent(ev)
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        // Allow dragging only if the view is visible and not animating
        if (visibility != View.VISIBLE || animation != null && !animation.hasEnded()) {
            return super.onTouchEvent(event)
        }

        val x = event.rawX
        val y = event.rawY

        when (event.actionMasked) {
            MotionEvent.ACTION_DOWN -> {
                // 在 ACTION_DOWN 中也获取父布局尺寸，以防 onInterceptTouchEvent 未完全处理或父布局尺寸发生变化
                if (parent is ViewGroup) {
                    val p = parent as ViewGroup
                    if (p.width > 0) parentWidth = p.width
                    if (p.height > 0) parentHeight = p.height
                }
                lastX = x
                lastY = y
                isDragging = false
                attractAnimator?.cancel()
                return true
            }

            MotionEvent.ACTION_MOVE -> {
                val deltaX = x - lastX
                val deltaY = y - lastY

                if (!isDragging && (abs(deltaX) > touchSlop || abs(deltaY) > touchSlop)) {
                    isDragging = true
                }

                if (isDragging) {
                    var newX = getX() + deltaX
                    var newY = getY() + deltaY

                    // 确保在拖动过程中，如果父布局尺寸动态改变，能获取到最新的
                    if (parent is ViewGroup) {
                        val currentParent = parent as ViewGroup
                        if (currentParent.width > 0) parentWidth = currentParent.width
                        if (currentParent.height > 0) parentHeight = currentParent.height
                    }

                    // 限制 X 轴拖动范围
                    if (parentWidth > 0 && width > 0) { // 增加 width > 0 的判断，防止视图尚未测量完成时出错
                        newX = newX.coerceIn(0f, (parentWidth - width).toFloat())
                    } else if (parentWidth <= 0 && width > 0) { // 如果父布局宽度无效，则不允许水平移动
                        newX = getX()
                    }


                    // 新增：限制 Y 轴拖动范围
                    if (parentHeight > 0 && height > 0) { // 增加 height > 0 的判断
                        newY = newY.coerceIn(0f, (parentHeight - height).toFloat())
                    } else if (parentHeight <= 0 && height > 0) { // 如果父布局高度无效，则不允许垂直移动
                        newY = getY()
                    }


                    setX(newX)
                    setY(newY)

                    lastX = x
                    lastY = y
                }
                return true
            }

            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                parent.requestDisallowInterceptTouchEvent(false)
                if (isDragging) {
                    attractToNearestPermittedEdge()
                    isDragging = false
                } else {
                    performClick()
                }
                return true
            }
        }
        return super.onTouchEvent(event)
    }

    private fun attractToNearestPermittedEdge() {
        if (parent !is ViewGroup) return // 父布局必须是 ViewGroup
        val currentParent = parent as ViewGroup
        // 确保在吸附时使用最新的父布局宽度
        if (currentParent.width <= 0) return
        parentWidth = currentParent.width


        val currentCenterX = getX() + width / 2f
        val parentCenterX = parentWidth / 2f

        val targetLeft = 0f
        val targetRight = (parentWidth - width).toFloat()

        var targetX: Float? = null // 改为可空类型，因为可能没有允许的吸附边缘

        if (targetRight < targetLeft) { // 如果视图比父布局还宽，则不进行吸附或居中处理
            // 可以选择将视图X坐标设置为0，或者不作处理
            // setX(0f)
            return
        }


        if (attractToLeftEdgeEnabled && attractToRightEdgeEnabled) {
            targetX = if (currentCenterX < parentCenterX) targetLeft else targetRight
        } else if (attractToLeftEdgeEnabled) {
            targetX = targetLeft
        } else if (attractToRightEdgeEnabled) {
            targetX = targetRight
        }
        // 如果 targetX 仍然是 null (例如左右吸附都禁用了), 则不执行动画
        if (targetX == null || getX() == targetX) return


        attractAnimator?.cancel()
        attractAnimator = ValueAnimator.ofFloat(getX(), targetX).apply {
            duration = 300
            interpolator = DecelerateInterpolator()
            addUpdateListener { animation ->
                setX(animation.animatedValue as Float)
            }
            start()
        }
    }

    override fun performClick(): Boolean {
        super.performClick()
        return true
    }

    fun setAttractToLeftEdge(enabled: Boolean) {
        attractToLeftEdgeEnabled = enabled
    }

    fun setAttractToRightEdge(enabled: Boolean) {
        attractToRightEdgeEnabled = enabled
    }

    // --- Shadow Methods ---
    fun setShadowElevationValue(elevationPx: Float) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            this.elevation = elevationPx
        }
    }

    fun setShadowColorValue(@ColorInt color: Int) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            outlineAmbientShadowColor = color
            outlineSpotShadowColor = color
        }
    }

    fun setShadowAmbientColorValue(@ColorInt color: Int) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            outlineAmbientShadowColor = color
        }
    }

    fun setShadowSpotColorValue(@ColorInt color: Int) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            outlineSpotShadowColor = color
        }
    }

    // --- Animation Methods ---
    fun showWithAnimation() {
        if (visibility == View.VISIBLE && (animation == null || animation.hasEnded())) {
            return // Already visible and not animating
        }
        visibility = View.VISIBLE // Make it visible before animation starts for smooth transition
        val anim = AnimationUtils.loadAnimation(context, R.anim.slide_in_from_right)
        anim.setAnimationListener(object : Animation.AnimationListener {
            override fun onAnimationStart(animation: Animation?) {}
            override fun onAnimationEnd(animation: Animation?) {
                // Ensure view stays visible without animation artifacts
                clearAnimation()
                visibility = View.VISIBLE
            }
            override fun onAnimationRepeat(animation: Animation?) {}
        })
        startAnimation(anim)
    }

    fun hideWithAnimation() {
        if (visibility == View.GONE && (animation == null || animation.hasEnded())) {
            return // Already gone and not animating
        }
        val anim = AnimationUtils.loadAnimation(context, R.anim.slide_out_to_right)
        anim.setAnimationListener(object : Animation.AnimationListener {
            override fun onAnimationStart(animation: Animation?) {}
            override fun onAnimationEnd(animation: Animation?) {
                visibility = View.GONE
                clearAnimation() // Important to remove animation artifacts
            }
            override fun onAnimationRepeat(animation: Animation?) {}
        })
        startAnimation(anim)
    }
}
